/****************************************************************************
 * Elisa 1.0                                                                *
 *--------------------------------------------------------------------------*
 * Author: Laurent Granvilliers, Vincent Sorin                              *
 * Copyright (c) 2004 Laboratoire d'Informatique de Nantes Atlantique       *
 *--------------------------------------------------------------------------*
 * Elisa is distributed WITHOUT ANY WARRANTY. Read the associated           *
 * COPYRIGHT file for more details.                                         *
 *--------------------------------------------------------------------------*
 * elisa_observer.h                                                         *
 ****************************************************************************/


/**
 * @file elisa_observer.h
 * @brief Base classes for propagation management.
 */

#ifndef _elisa_observer_h_
#define _elisa_observer_h_ 1

#include <set>
#include <map>
#include "elisa_defs.h"
#include "elisa_event.h"
#include <iostream>

NAMESPACE_ELISA
/// @defgroup Observer Classes for pattern Observer

//--------------------------------------------------------------------------
// class Observer
//--------------------------------------------------------------------------

// forward declaration
class Subject;

/** @ingroup Observer
 * @class Observer
 * @brief Base class listeners of events on variable domains
 */
class Observer
{
public:
	/**
 	 * Default Constructor
 	 */
	Observer()
	{
	}

	Observer(const Observer & o)
	{
	}

	/**
 	 * Destructor
 	 */
	virtual
	~Observer()
	{
	}

	/**
 	 * Call of the listener
 	 * This method is called when the subject inform the listener something has happened
 	 */
	virtual void call()
	{
	}

	//virtual void
	// print(std::ostream& os, std::string s, VecConstraints* v) const = 0 ;
};



//--------------------------------------------------------------------------
// class Subject
//--------------------------------------------------------------------------

/**
 * @ingroup Observer
 * @class SetObserver
 * @brief Set of listeners
 */
typedef std::set<Observer *> SetObserver;


/**
 * @ingroup Observer
 * @class MapObserver
 * @brief Map of listeners
 */
typedef std::map<int, SetObserver *, ltint> MapObserver;

/**
 * @ingroup Observer
 * @class Subject
 * @brief Subject to listen for listener
 */
class Subject
{
public:
	/**
 	 * Default constructor
 	 */
	Subject()
	{
	};

	Subject(const Subject & s)
	{
		_observers = s._observers;
	}

	/**
 	 * Declares that l listens to modifications of this Subject
 	 * @param l a listener interested by modifications of this Subject
 	 */
	void dependsOn(Observer *l, ElisaEvent e)
	{
		if (l != 0) {
			if (_observers[e] == 0) {
				_observers[e] = new SetObserver();
			}

			_observers[e]->insert(l);
		}
	}

	/**
 	 * Call of listeners when a modification of domain happens
 	 */
	void notifyChange(ElisaEvent e)
	{
		SetObserver *temp = _observers[e];
		if (temp != 0) {
			SetObserver::const_iterator it;
			for (it = temp->begin(); it != temp->end(); ++it) {
				(*it)->call();
			}
		}
	}

	// @var listeners of domain modifications
	MapObserver _observers;
};

END_NAMESPACE_ELISA
#endif // ELISA_OBSERVER_H
